﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Luna;
using System.Text.RegularExpressions;
using System.Diagnostics;

namespace TextDataExtractor.DEML {

	public enum FindTextLocatorOperation { NoOP, Equal, CloseTag, Match }

	public class FindTextLocator: DemlElement, ITextLocator  {

		private FindTextLocatorOperation op = FindTextLocatorOperation.NoOP;
		private Match match;
		private Regex pattern;

		public FindTextLocatorOperation  FindOperation {
			get {
				if (op == FindTextLocatorOperation.NoOP) {
					string optext = getArgument("op").Replace("-", "");
					Enum.TryParse<FindTextLocatorOperation>(optext, true, out op);
				}
				return op;
			}
			set {
				op = value;
			}
		}

		public string Value {
			get { return getArgument("value"); }
			set { Arguments["value"] = value; }
		}

		public Regex Pattern {
			get {
				return pattern != null && FindOperation == FindTextLocatorOperation.Match ? pattern :
					(pattern = new Regex(Value, RegexOptions.Multiline | RegexOptions.Compiled));
			}
		}

		public string MatchedText { get; protected set; }

		public int Length { get; protected set; }

		public object getDataItem(object index) {
			object result = null;
			if (index == null)
				return this;
			else {
				int idx = index.ToString().toInt();
				if (idx == 0)
					return MatchedText;
				else if (match != null && match.Success)
					return match.Groups[idx].Value;
			}
			return result;
		}

		public int locate(int sidx, string input) {
			int result = -1;
			switch (FindOperation) {
				case FindTextLocatorOperation.Equal:
					result = input.IndexOf(Value, sidx);
					Length = Value.Length;
					MatchedText = result >= 0 ? Value : string.Empty;

					break;
				case FindTextLocatorOperation.Match:
					match = Regex.Match(sidx > 0 ? input.Substring(sidx) : input, Value, RegexOptions.Multiline);
					if (match.Success) {
						result = sidx + match.Index;
						Length = match.Length;
						MatchedText = match.Groups[0].Value;
					}
					break;
				case FindTextLocatorOperation.CloseTag:
					string endtag = "</" + Value + ">";
					string begtag = "<" + Value;
					result = input.IndexOf(endtag, sidx);
					while (result >= 0) {
						int begTagCount = 0;
						int tempSidx = sidx;
						while ((tempSidx = input.IndexOf(begtag, sidx)) >= 0 && tempSidx < result) {
							begTagCount++;
							sidx = tempSidx + 1;
						}

						for (int i = 0; i < begTagCount && result >= 0; i++)
							result = input.IndexOf(endtag, result + 1);

						if (begTagCount == 0) break;
					}

					Length = endtag.Length;
					MatchedText = endtag;
					break;
			}
			return result;
		}

		public override void CopyTo(DemlElement target) {
			base.CopyTo(target);
			FindTextLocator p = (FindTextLocator)target;
			p.op = op;
			p.pattern = this.Pattern;
		}

		protected void test() {
			//--------------01234567890123456789012345678901234567890123
			string input = "<a:1><a:2><a:3><a:4></a>:4</a>:3</a>:2</a>:1";
			FindOperation = FindTextLocatorOperation.CloseTag;
			Value = "a";
			int i = locate(6, input);
			Trace.WriteLine(i);
			
			FindOperation = FindTextLocatorOperation.Match;
			//--------01234567890123456789012345678901234567890
			input = @"<a meo=12-23><a><a meo=12-2123><a></a></a></a></a>";
			Value = @"meo=\d+-\d+";
			Trace.WriteLine(locate(0, input) + ", " + Length.ToString());
			Trace.WriteLine(locate(5, input) + ", " + Length.ToString());
		}
	}
}
